#!/usr/bin/env python
# coding: utf-8

# ## 期末实践要求

# >**CNKI 文章下载：**  
# 1.提交ipynb档或者可执行.py项目文件  
# 2.有较好的文档描述和数据描述（包含数据目标和数据结果描述）  
# 3.主要目标：可对CNKI PDF文件进行依次下载，解决中间处理问题（并做描述）  
# 4.次要目标：数据分析（关键词替换）——数据可视化（VOSviewer--keywords_co-occurrence）  
# 5.将作业上传至gitee/github，作为数据挖掘项目作品  

# ## CNKI_Selenium

# In[45]:


import pandas as pd
import numpy as np
from lxml.html import fromstring
import time
import re
from random import random
import requests_html
from requests_html import HTMLSession
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities


# ## 使用Selenium
# * 要更改 opts.binary_location 至自己本地的Chrome浏览器，建议portable
# * Chrome浏览器 和 chromedriver.exe要同版本号到小数后一位
# * 要确保可以 开启浏览器机器人
# * 要确保浏览器机器人 可以打开网页 driver.get("https://mp.weixin.qq.com")

# In[46]:


import selenium
help(selenium)


# In[47]:


# coding=utf-8
from selenium import webdriver
import time

wd = webdriver.Chrome()
wd.get("https://www.baidu.com")    # 打开百度浏览器
wd.find_element_by_id("kw").send_keys("selenium")   # 定位输入框并输入关键字
wd.find_element_by_id("su").click()   #点击[百度一下]搜索
time.sleep(3)   #等待3秒
wd.quit()   #关闭浏览器


# In[48]:


from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities


#caps=dict()
#caps["pageLoadStrategy"] = "none"   # Do not wait for full page load

opts = webdriver.ChromeOptions()
opts.add_argument('--no-sandbox')#解决DevToolsActivePort文件不存在的报错
opts.add_argument('window-size=1920x3000') #指定浏览器分辨率
opts.add_argument('--disable-gpu') #谷歌文档提到需要加上一这个属性来规避bug
opts.add_argument('--hide-scrollbars') #隐藏滚动条, 应对些特殊页面

driver = webdriver.Chrome( chrome_options = opts) #desired_capabilities=caps,


# In[49]:


driver.get("https://www.cnki.net/")


# ### 检查登录状态

# In[50]:


driver.find_element_by_id('Ecp_loginShowName1').get_attribute('innerHTML')


# ## 高级检索

# ### 检查窗口

# In[51]:


element = driver.find_element_by_xpath('//*[@id="highSearch"]')
element.click()


# In[52]:


driver.switch_to.window(driver.window_handles[1])


# In[53]:


# 检查当前所在窗口
driver.current_window_handle


# ### 检索前期准备

# In[54]:


# 选择学术期刊
driver.find_element_by_xpath('//li[@data-id="xsqk"]').click()


# In[55]:


# 点击专业检索
driver.find_element_by_name('majorSearch').click()


# In[56]:


#勾选期刊类型
# SCI
element = driver.find_element_by_xpath('/html/body/div[2]/div/div[2]/div/div[1]/div[1]/div[2]/div[1]/div[3]/div/label[2]/input')
element.click()
# 北大核心
element = driver.find_element_by_xpath('/html/body/div[2]/div/div[2]/div/div[1]/div[1]/div[2]/div[1]/div[3]/div/label[4]/input')
element.click()
# CSSCI
element = driver.find_element_by_xpath('/html/body/div[2]/div/div[2]/div/div[1]/div[1]/div[2]/div[1]/div[3]/div/label[5]/input')
element.click()
#CSCD
driver.find_element_by_xpath('//div[@class="extend-tit-labels"]//input[@key="CSD"]').click()


# In[57]:


# 设置query
大数据_平台_query = '(SU="大数据" and SU="平台") '


# In[58]:


element = driver.find_element_by_xpath('/html/body/div[2]/div/div[2]/div/div[1]/div[1]/div[2]/textarea')
element.clear()


# In[59]:


#输入关键词
element = driver.find_element_by_xpath('/html/body/div[2]/div/div[2]/div/div[1]/div[1]/div[2]/textarea').send_keys(大数据_平台_query)


# ### 检索结果

# In[60]:


#点击检索
element = driver.find_element_by_xpath('/html/body/div[2]/div/div[2]/div/div[1]/div[1]/div[2]/div[2]/input')
element.click()


# In[61]:


# 检索文章的总数量
element = driver.find_element_by_xpath('//*[@id="countPageDiv"]/span[1]/em')
element.get_attribute('innerHTML')


# In[64]:


#更换每页文章数量为50
element = driver.find_element_by_xpath('/html/body/div[3]/div[2]/div[2]/div[2]/form/div/div[1]/div[2]/div[2]/div/div/div/i')
element.click()


# In[65]:


element = driver.find_element_by_xpath('/html/body/div[3]/div[2]/div[2]/div[2]/form/div/div[1]/div[2]/div[2]/div/div/ul/li[3]/a')
element.click()


# In[66]:


# 获取跳转上限
element = driver.find_element_by_xpath('//span[@class="countPageMark"]')
element.get_attribute('innerHTML')


# In[67]:


# 查看第一页页面信息
element = driver.find_element_by_id('gridTable')
第一页_html = element.get_attribute('innerHTML')
第一页数据 = pd.read_html(第一页_html)[0]
第一页数据


# ## 导出refworks文件
# >由于限制最大勾选为500项，因此分批下载

# In[68]:


# 第一次
pages = list(range(1,11))
print(pages)


# In[69]:


# 选中页面50篇 —> 翻页
def fangye(pages):
    for p in pages:
        print (p,end='\t')
        全选 = driver.find_element_by_xpath('//*[@id="selectCheckAll1"]')
        全选.click()
        跳转 = driver.find_element_by_id('PageNext')
        跳转.click()
        time.sleep(10+10*random())


# In[70]:


# 翻页操作
fangye(pages)


# ### 第一轮下载

# In[71]:


# 选择导出
element = driver.find_element_by_xpath('/html/body/div[3]/div[2]/div[2]/div[2]/form/div/div[1]/div[2]/ul[1]/li[2]/i')
element.click()


# In[72]:


# 选择导出格式
element = driver.find_element_by_xpath('/html/body/div[3]/div[2]/div[2]/div[2]/form/div/div[1]/div[2]/ul[1]/li[2]/ul/li[1]/a')
element.click()


# In[73]:


# 选择refworks文件
element = driver.find_element_by_xpath('/html/body/div[3]/div[2]/div[2]/div[2]/form/div/div[1]/div[2]/ul[1]/li[2]/ul/li[1]/ul/li[8]/a')
element.click()


# In[74]:


# 窗口切换
driver.switch_to_window(driver.window_handles[2])


# In[180]:


# 批量导出
element = driver.find_element_by_xpath('/html/body/div[3]/div/div[2]/div[1]/ul/li[3]')
element.click()


# In[181]:


# 窗口切换
driver.switch_to_window(driver.window_handles[1])


# ### 第二轮下载

# In[182]:


# 清除选中
driver.find_element_by_xpath('//*[@id="gridTable"]/div[1]/div[2]/div[1]/a').click()


# In[183]:


# 第二轮下载
pages = list(range(12,21))
print(pages)


# In[184]:


# 翻页操作
fangye(pages)


# In[185]:


# 选择导出
element = driver.find_element_by_xpath('/html/body/div[3]/div[2]/div[2]/div[2]/form/div/div[1]/div[2]/ul[1]/li[2]/i')
element.click()
# 选择导出格式
element = driver.find_element_by_xpath('/html/body/div[3]/div[2]/div[2]/div[2]/form/div/div[1]/div[2]/ul[1]/li[2]/ul/li[1]/a')
element.click()
# 选择refworks文件
element = driver.find_element_by_xpath('/html/body/div[3]/div[2]/div[2]/div[2]/form/div/div[1]/div[2]/ul[1]/li[2]/ul/li[1]/ul/li[8]/a')
element.click()


# In[186]:


print (driver.window_handles)


# In[187]:


# 检查当前所在窗口
driver.current_window_handle


# In[189]:


# 窗口切换
driver.switch_to_window(driver.window_handles[3])


# In[190]:


# 批量导出
element = driver.find_element_by_xpath('/html/body/div[3]/div/div[2]/div[1]/ul/li[3]')
element.click()


# In[75]:


# 窗口切换
driver.switch_to_window(driver.window_handles[1])


# In[76]:


# 清除选中
driver.find_element_by_xpath('//*[@id="gridTable"]/div[1]/div[2]/div[1]/a').click()


# In[77]:


# 返回第一页
driver.find_element_by_xpath('/html/body/div[3]/div[2]/div[2]/div[2]/form/div/div[2]/a[1]').click()


# In[213]:


with open('refwork文件.txt', encoding='utf-8') as f:
    display(f.readlines())


# ## PDF下载

# ### 获取详情页链接

# In[78]:


# 解析页面获取链接
html=driver.page_source
root=fromstring(html)
href = [x for x in root.xpath('.//*[@id="gridTable"]/table/tbody/tr/td[2]/a/@href')]
# 将获取的链接改为正确的链接
c_link=['https://kns.cnki.net/kcms/detail/detail.aspx?'+x.split('&')[6]+'&'+x.split('&')[5]+'&'+x.split('&')[4] for x in href]
c_link


# In[79]:


links=[]
for link in c_link:
#     link=correct(link)
    links.append(link)
    df_links=pd.DataFrame({'页面链接':links})
    df_第一页=pd.concat([pd.read_html(第一页_html)[0],df_links],axis=1)
df_第一页 


# ## 获取pdf下载链接

# In[80]:


# 获取详细页面中的PDF下载链接
from requests_html import HTMLSession
import urllib.parse

session = HTMLSession()

pdf_links=[]

for url in links:
    r = session.get(url)
    pdf_link_xpath=r.html.xpath('//*[@id="pdfDown"]/@href')[1]
    pdf_links.append(pdf_link_xpath)

pdf_links


# In[81]:


# 完整的PDF下载链接
pdf_href=['https://kns.cnki.net'+link for link in pdf_links]
pdf_href


# In[82]:


df_pdf_links=pd.DataFrame({'PDF下载链接':pdf_href})
df_第一页=pd.concat([df_第一页,df_pdf_links],axis=1)
df_第一页


# In[83]:


# 翻页
element = driver.find_element_by_id('PageNext')
element.get_attribute('innerHTML')


# In[84]:


表格_html = dict()
main_content =""
element = None


# In[85]:


# 所有页数
pages = list(range(1,20))
print(pages)


# In[86]:


# 函数（翻页）
def process_pages (pages):
    for p in pages:
        print (p,end='\t')
        # 定位到“下一页”的按钮 ——> 点击
        跳转 = driver.find_element_by_id('PageNext')
        跳转.click()
        # 设定休息的时间 ——> 避免爬虫被禁报错、以及出现验证码
        time.sleep(10+20*random())
        # 获取含有页面主要数据的表格
        element = driver.find_element_by_id('gridTable')
        main_content = element.get_attribute('innerHTML')
        表格_html[p] = main_content


# In[87]:


# 翻页操作
process_pages(pages)


# In[88]:


df = pd.DataFrame([表格_html]).T
df.columns = ["html_snippets"]
display(df)


# In[89]:


l_df = []
for p in pages:
    表格 = pd.read_html(表格_html[p])[0]
    l_df.append(表格)


# In[90]:


# 获取全部页面（21页）内容信息
df_url_out = pd.concat(l_df).reset_index(drop=True)
df_总表 = 第一页数据.append(df_url_out).reset_index()
df_总表


# ### 翻页获取全部详情页链接、pdf下载链接

# In[91]:


# 检查翻页后一共获取了 id为gridTable的标签
raw = [表格_html[p] for p in pages]
len(raw)


# In[92]:


# 解析 —— 详情页链接
root_group = []
for i in raw:
    root = fromstring(i)
    root_group.append(root)
print(len(root_group))

# 获取详情页链接
links_all = []
for j in root_group:
    links_all.extend(j.xpath('//table[@class="result-table-list"]/tbody//td[@class="name"]/a/@href'))
print(len(links_all))
links_all

# 将详情页链接修改成正确形式
all_correct_url = []
for i in links_all:
    b = i.replace('/KNS8/Detail?','https://kns.cnki.net/kcms/detail/detail.aspx?')
    all_correct_url.append(b)
all_correct_url


# In[93]:


# 合并链接 —— 与首页的链接合并得到全部链接 可通过检查长度 len(list_all_url) 得知是否正确
list_all_url = []
for item in c_link:
    list_all_url.append(item)
for item in all_correct_url:
    list_all_url.append(item)
list_all_url


# In[ ]:


# 获取每篇文章的pdf下载链接
all_pdf_url = []
for i in all_correct_url:
    session = HTMLSession()
    r = session.get(i)
    all_pdf_url_xpath = r.html.xpath('//a[@id="pdfDown"]/@href')[0]
    all_pdf_url.append(all_pdf_url_xpath)
print(len(all_pdf_url))

# 将获取到的pdf链接改成正确的链接
all_pdf_correct_url = ['https://kns.cnki.net'+ link for link in all_pdf_url]
all_pdf_correct_url


# In[ ]:


# 获取完整的PDF链接
pdf_links_correct=['https://kns.cnki.net'+link for link in pdf_links]
df_pdf_download=pd.DataFrame({'PDF下载链接':pdf_links_correct})


# In[ ]:


# 合并pdf链接
list_all_pdf_url = []
for item in pdf_href:
    list_all_pdf_url.append(item)
for item in all_pdf_correct_url:
    list_all_pdf_url.append(item)
list_all_pdf_url


# In[ ]:


# 将获取到的详情页链接与pdf下载链接转换为表格
df_url = pd.DataFrame({'详情页链接':list_all_url,'pdf':list_all_pdf_url}).reset_index()
df_url


# In[ ]:


# 合并表格【页面内容与链接】
df_all_information = pd.concat([df_总表,df_url],axis=1)
df_all_information


# In[ ]:


# 将表格存到本地
with pd.ExcelWriter('CNKI文章数据.xlsx',mode='w',engine="openpyxl") as writer:  
            df_all_information.to_excel(writer,sheet_name="知网数据")


# ### 下载pdf
# > 调用图鉴API

# In[268]:


opts = webdriver.ChromeOptions()
opts.add_argument('--no-sandbox')#解决DevToolsActivePort文件不存在的报错
opts.add_argument('window-size=1920x3000') #指定浏览器分辨率
opts.add_argument('--disable-gpu') #谷歌文档提到需要加上一这个属性来规避bug
opts.add_argument('--hide-scrollbars') #隐藏滚动条, 应对些特殊页面
options = webdriver.ChromeOptions()
out_path = r'C:\Users\13724\Desktop\数据挖掘\web mining\week14\pdf'  # 是你想指定的路径
prefs = {'profile.default_content_settings.popups': 0, 'download.default_directory': out_path}
options.add_experimental_option('prefs', prefs)
driver = webdriver.Chrome(executable_path=r'C:\Program Files\Google\Chrome\Application\chromedriver.exe', chrome_options=options)
#driver = webdriver.Chrome( chrome_options = opts) #desired_capabilities=caps


# In[269]:


def yanzhenma_api(uname, pwd, img, typeid):
    with open(img, 'rb') as f:
        base64_data = base64.b64encode(f.read())
        b64 = base64_data.decode()
    data = {"username": uname, "password": pwd, "typeid": typeid, "image": b64}
    result = json.loads(requests.post("http://api.ttshitu.com/predict", json=data).text)
    if result['success']:
        return result["data"]["result"]
    else:
        return result["message"]
    return ""


# In[ ]:


# 读取上面已保存在本地的xlsx文件【利用里面的pdf下载链接】
data = pd.read_excel("CNKI文章数据.xlsx") 
base = "https://kns.cnki.net/"
# 开始与结束的链接序号 count end_count
count = 1
end_count = 1000
# 读取title、pdf链接
title_list = data["篇名"].to_list()[count:end_count]
download_url_list = data["pdf"].to_list()[count:end_count]
list_all_url_list = data["详情页链接"].to_list()[count:end_count]
for title,download_url,list_all_url in zip(title_list,download_url_list,list_all_url_list):
    try:
        # 进入pdf的下载链接
        driver.get(download_url)
        time.sleep(5)
        # 出现验证码的情况
        if driver.find_element_by_xpath('//*[@id="vImg"]'):
            time.sleep(5)
            ele = driver.find_element_by_id('vImg')
            ele.screenshot('ele.png')
            #截取全屏后定位截图里验证码的位置，并重新裁剪保存
            # api识别部分
            img_path = "C:/Users/Downloads/ele.png"
            result = yanzhenma_api(uname='trevor', pwd='18078846977',img=img_path,typeid=3)
            # 输出识别出的验证码
            print("验证码识别：",result) 
            # 将验证码填入
            driver.find_element_by_id('vcode').send_keys(result)
            time.sleep(5)
            # 点击验证码的提交，然后开始下载
            driver.find_element_by_xpath('/html/body/div/form/dl/dd/button').click()
    except:
        print(f'{title}----已下载')
        continue 


# In[ ]:





# In[ ]:





# In[ ]:





# In[ ]:




